#include "rtx.h"
#include "rtx_inc.h"
#include "i_processes.h"
#include "debug.h"
#include "globals.h"
#include "context.h"
#include "processes.h"

VOID uart_handler (VOID)
{
	// Disable interrupts so that this won't get interrupted
	asm( "move.w #0x2700,%sr" );

	// Back-up all of our registers to the stack to ensure that we do not lose any information
	asm( "move.l %d0, -(%a7)" );
    asm( "move.l %d1, -(%a7)" );
    asm( "move.l %d2, -(%a7)" );
    asm( "move.l %d3, -(%a7)" );
    asm( "move.l %d4, -(%a7)" );
    asm( "move.l %d5, -(%a7)" );
    asm( "move.l %d6, -(%a7)" );
    asm( "move.l %d7, -(%a7)" );
    asm( "move.l %a0, -(%a7)" );
    asm( "move.l %a1, -(%a7)" );
    asm( "move.l %a2, -(%a7)" );
    asm( "move.l %a3, -(%a7)" );
    asm( "move.l %a4, -(%a7)" );
    asm( "move.l %a5, -(%a7)" );
    asm( "move.l %a6, -(%a7)" );


	asm( "move.l #0, %d1 ");
    asm( "move.l %d1, -(%a7) " );

    asm ( "jsr h_exception_handler" );

    asm( "move.l (%a7)+, %d1" );

	asm( "move.l (%a7)+, %a6" );
    asm( "move.l (%a7)+, %a5" );
    asm( "move.l (%a7)+, %a4" );
    asm( "move.l (%a7)+, %a3" );
    asm( "move.l (%a7)+, %a2" );
    asm( "move.l (%a7)+, %a1" );
    asm( "move.l (%a7)+, %a0" );
    asm( "move.l (%a7)+, %d7" );
    asm( "move.l (%a7)+, %d6" );
    asm( "move.l (%a7)+, %d5" );
    asm( "move.l (%a7)+, %d4" );
    asm( "move.l (%a7)+, %d3" );
    asm( "move.l (%a7)+, %d2" );
    asm( "move.l (%a7)+, %d1" );
    asm( "move.l (%a7)+, %d0" );

	asm( "unlk %a6" );
	asm( "rte" );
}

VOID timer_handler (VOID)
{
	// Disable interrupts so that this won't get interrupted
	asm( "move.w #0x2700,%sr" );

	// Back-up all of our registers to the stack to ensure that we do not lose any information
	asm( "move.l %d0, -(%a7)" );
    asm( "move.l %d1, -(%a7)" );
    asm( "move.l %d2, -(%a7)" );
    asm( "move.l %d3, -(%a7)" );
    asm( "move.l %d4, -(%a7)" );
    asm( "move.l %d5, -(%a7)" );
    asm( "move.l %d6, -(%a7)" );
    asm( "move.l %d7, -(%a7)" );
    asm( "move.l %a0, -(%a7)" );
    asm( "move.l %a1, -(%a7)" );
    asm( "move.l %a2, -(%a7)" );
    asm( "move.l %a3, -(%a7)" );
    asm( "move.l %a4, -(%a7)" );
    asm( "move.l %a5, -(%a7)" );
    asm( "move.l %a6, -(%a7)" );

	asm( "move.l #1, %d1 ");
    asm( "move.l %d1, -(%a7)" );

    asm ( "jsr h_exception_handler" );

    asm( "move.l (%a7)+, %d1" );

	asm( "move.l (%a7)+, %a6" );
    asm( "move.l (%a7)+, %a5" );
    asm( "move.l (%a7)+, %a4" );
    asm( "move.l (%a7)+, %a3" );
    asm( "move.l (%a7)+, %a2" );
    asm( "move.l (%a7)+, %a1" );
    asm( "move.l (%a7)+, %a0" );
    asm( "move.l (%a7)+, %d7" );
    asm( "move.l (%a7)+, %d6" );
    asm( "move.l (%a7)+, %d5" );
    asm( "move.l (%a7)+, %d4" );
    asm( "move.l (%a7)+, %d3" );
    asm( "move.l (%a7)+, %d2" );
    asm( "move.l (%a7)+, %d1" );
    asm( "move.l (%a7)+, %d0" );

	asm( "unlk %a6" );
	asm( "rte" );
}

VOID h_exception_handler (UINT32 device)
{
	current_process->process_state = INTERRUPTED;
	save_proc = current_process;

	switch(device)
	{
		case 0: // UART
			context_switch(current_process, get_pcb(UART_I_PROCESS));
		break;
		case 1: // Timer
			context_switch(current_process, get_pcb(TIMER_I_PROCESS));
		break;
	}
}
